package classloader;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Objects;

/**
 * @Author: Hugh
 * @Date: 2021/2/28
 */
public class MyClassLoader extends ClassLoader{
    private String codePath;

    private static  MyClassLoader myClassLoader;

    private MyClassLoader(ClassLoader parent, String codePath) {
        super(parent);
        this.codePath = codePath;
    }
    private MyClassLoader(){}

    public MyClassLoader(String codePath) {
        this.codePath = codePath;
    }

    public static synchronized MyClassLoader getInstance(ClassLoader parent, String codePath){
        if(Objects.isNull(myClassLoader)){
            synchronized (MyClassLoader.class){
                if(Objects.nonNull(parent)) {
                    myClassLoader = new MyClassLoader(parent, codePath);
                }else{
                    myClassLoader = new MyClassLoader(codePath);
                }
            }
        }
        return null;
    }
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        BufferedInputStream bis = null;
        ByteArrayOutputStream baos = null;
        try {
            //1.字节码路径
            String fileName = this.codePath + name + ".class";
            //2.获取输入流
            bis = new BufferedInputStream(new FileInputStream(fileName));
            //3.获取输出流
            baos = new ByteArrayOutputStream();
            //4.io读写
            int len;

            byte[] data = new byte[1024];
            while ((len = bis.read(data)) != -1){
                baos.write(data , 0 , len);
            }
            //5.获取内存中字节数组
            byte[] byteCode = baos.toByteArray();
            //6.调用defineClass 将字节数组转成Class对象
            return defineClass(null, byteCode, 0, byteCode.length);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                assert bis != null;
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                assert baos != null;
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
